iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 23
0
Software Development

認識scala系列 第 23

Scala day 23 (implicit conversion)

  • 分享至 

  • xImage
  •  

implicit conversion

就是在當某物件沒有要呼叫的方法時,可以定義 implicit function 編譯器會嘗試使用 implicit function 來呼叫,將原物件轉換成另一個物件.
由於 Int 沒有 append 方法所以下面執行會失敗 :

scala> 1 append 2
<console>:13: error: value append is not a member of Int
       1 append 2
         ^

定義一個 MyAppend 及 append 方法 :

scala> class MyAppend(num: Int) {
     |  def append(newNum: Int) = num.toString + newNum.toString
     | }
defined class MyAppend

在 REPL 直接寫 implicit 會出現 warning,但還是可以使用的 :

scala> implicit def intToMyAppend(x:Int) = new MyAppend(x)
<console>:13: warning: implicit conversion method intToMyAppend should be enabled
by making the implicit value scala.language.implicitConversions visible.
This can be achieved by adding the import clause 'import scala.language.implicitConversions'
or by setting the compiler option -language:implicitConversions.
See the Scaladoc for value scala.language.implicitConversions for a discussion
why the feature should be explicitly enabled.
       implicit def intToMyAppend(x:Int) = new MyAppend(x)
                    ^
intToMyAppend: (x: Int)MyAppend

如果不要有 warning 可以 import scala.language.implicitConversions :

scala> import scala.language.implicitConversions
import scala.language.implicitConversions

scala> implicit def intToMyAppend(x:Int) = new MyAppend(x)
intToMyAppend: (x: Int)MyAppend

加上 implicit 函式後,編譯器會在範圍內找到對應型態的 implicit 函式呼叫.所以會變成 intToMyAppend(1) append 2

scala> 1 append 2
res8: String = 12

也可以把 implicit 函式抽成一個 object.

寫一隻 MyAppend.scala 並 compiler :

class MyAppend(num: Int) {
 def append(newNum: Int) = num.toString + newNum.toString
}

scalac MyAppend.scala

寫一隻 MyConvert.scala 並 compiler :

object MyConvert {
 implicit def intToMyAppend(x:Int) = new MyAppend(x)
}

scalac MyConvert.scala

寫一隻 ConvertTest.scala,並將有定義隱含函式的 object(MyConvert) import 進來 :

import MyConvert._

object ConvertTest {
    def main(args: Array[String]): Unit = {
    val result = 1 + 2
    println(result)
    val res = 1 append 2
    println(res)
  }
}

接著執行 ConvertTest.scala :

daniel@Danielde-MacBook-Pro > scala ConvertTest.scala
3
12

在方法裡使用 implicit 物件,如果使用該方法時沒傳入物件,則會使用 implicit 物件傳入.
寫一隻 Employees.scala,並 compiler :

class Employees(name:String ,val amt:Int) {
  def getName = name
}

object Employees {

  import Employees._

  implicit val employee: Employees = new Employees("Daniel",50)

  def sayHello(implicit employee: Employees) = "Hello " + employee.getName
}


scalac Employees.scala

寫一隻 EmployeesTest.scala,sayHello 沒給參數的話,會帶隱含物件,所以會印出 Daniel.

object EmployeesTest {
  def main(args: Array[String]): Unit = {
    println(Employees.sayHello)//Hello Daniel
    println(Employees.sayHello(new Employees("Sam",5000)))//Hello Sam
  }
}

執行時,加上 classpath :

daniel@Danielde-MacBook-Pro > scala -cp "./" EmployeesTest.scala
Hello Daniel
Hello Sam

總結


  • 在 scala 的 implicit conversion 主要是透過型態來找到對應,並不是 function 或變數的名稱找.

上一篇
Scala day 22 (Companion Object & apply & update)
下一篇
Scala day 24 (variances)
系列文
認識scala30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言